package ch.areion.observator.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import ch.areion.common.message.Message;
import ch.areion.common.message.Module;
import ch.areion.common.message.Type;
import ch.areion.common.message.Version;

/**
 * Class for handling client connections.
 * @author leupibr
 * 
 */
public class ClientConnection implements Runnable {
	public static int ClientCount = 0;
	/**
	 * The observer.
	 */
	private MessageListener observer;

	/**
	 * Flag for closing connection
	 */
	private boolean close = false;

	private Socket socket;
	/**
	 * Reader for incoming messages.
	 */
	private BufferedReader in;

	/**
	 * Constructor
	 * @param s The client socket
	 * @throws IOException Unable to open buffer
	 */
	public ClientConnection(Socket s, MessageListener o) throws IOException {
		this.observer = o;
		this.socket = s;
		this.in = new BufferedReader(new InputStreamReader(s.getInputStream()));
		ClientConnection.ClientCount++;
	}

	@Override
	public void run() {
		// listens to input buffer
		listen();

		// close buffer
		if(in != null) {
			try {
				in.close();
			}
			catch(IOException e) {
				System.err.println("Unable to close in buffer from client connection. "
				    + e);
			}
		}

		// close socket
		if(socket != null) {
			try {
				socket.close();
			}
			catch(IOException e) {
				System.err.println("Unable to close socket client connection. " + e);
			}
		}
	}

	/**
	 * Listens to client and generates new messages.
	 */
	private void listen() {
		String input;

		while(!close) {
			try {
				input = in.readLine();
				if(input == null) {
					ClientCount--;
					observer.clientDown(this);
					close = true;
				}
				else {
					if(!input.trim().equals("")) {
						observer.messageReceived(new Message(input));
					}
				}
			}
			catch(IOException ex) {
				observer.messageReceived(new Message(Version.V01, Type.ERROR,
				    Module.COMMUNICATION, "Error while reading data - "
				        + ex.getMessage()));
			}
		}
	}

	/**
	 * Set close flag.
	 */
	public void close() {
		this.close = true;
	}

	/**
	 * Returns the ip address of the connected client
	 * @return The ip address of the connected client
	 */
	public String getAddress() {
		return socket.getInetAddress().getHostAddress();
	}
}
